<?php
/**
 * User：liujun
 * Date：2024/5/11
 * Time：16:52
 */

namespace Encore\Admin\Controllers;

use Encore\Admin\Auth\Database\Configuration;
use Encore\Admin\Form;
use Encore\Admin\Layout\Content;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;

class ConfigurationController extends AdminController
{
    use ValidatesRequests;

    /**
     * @var Configuration
     */
    private $model;
    private Collection $configurations;

    protected $title = '系统配置';

    public function __construct()
    {
        $m = config('admin.database.configurations_model');

        $this->model = new $m();
        $this->configurations = $this->model::orderBy('order')->get();

        parent::__construct();
    }

    public function index(Content $content): Content
    {
        return $content
            ->title($this->title())
            ->description('<code>建议系统加载时批量写入配置信息，提升效率。</code>')
            ->body($this->configForm());
    }

    public function batchUpdate(Request $request)
    {
        $configurations = $this->configurations;
        $rules = [];
        $attributes = [];
        collect($request->input())
            ->filter(fn($value, $key) => $configurations->contains('slug', $key))
            ->each(function ($value, $key) use (&$rules, &$attributes) {
                $config = $this->configurations->firstWhere('slug', $key);
                if ($config->rules) {
                    $rules[$key] = $config->rules;
                }
                $attributes[$key] = $config->name;
            })->toArray();

        $validator = validator($request->input(), $rules, [], $attributes);

        if ($validator->fails()) {
            return redirect(route('admin.auth.configurations.index'))->withInput()->withErrors($validator);
        }

        $configurations->each(function (Configuration $configuration) use ($request) {
            if ($request->has($configuration->slug)) {
                $value = $request->input($configuration->slug);
                if ($configuration->form_type === 'switch') {
                    $value = $value === 'on' ? 1 : 0;
                }
                $configuration->update(['value' => $value]);
            }
        });

        admin_toastr('系统配置更新成功');
        return redirect(route('admin.auth.configurations.index'));
    }

    private function configForm(): Form
    {
        $form = new Form($this->model);
        $form->setAction(admin_base_path('auth/configuration/batch/update'));
        foreach (config('admin.configuration_types') as $type => $name) {
            $form->tab($name, function (Form $form) use ($type) {
                $configurations = $this->configurations->where('type', $type);

                /** @var Configuration $configuration */
                foreach ($configurations as $configuration) {

                    $editUrl = route('admin.auth.configurations.edit', ['configuration' => $configuration->id]);

                    $helpWithLink = $configuration->help
                        ? ($configuration->help . " <a href='$editUrl'><i class='fa fa-edit'></i> {$configuration->slug}</a>")
                        : "<a href='$editUrl'><i class='fa fa-edit'></i> {$configuration->slug}</a>";

                    switch ($configuration->form_type) {
                        case 'text':
                            $form->text($configuration->slug, $configuration->name)
                                ->rules($configuration->rules)
                                ->append("<a href='$editUrl'><i class='fa fa-edit'></i> {$configuration->slug}</a>")
                                ->help($configuration->help)
                                ->value($configuration->value);
                            break;
                        case 'radio':
                            $form->radio($configuration->slug, $configuration->name)
                                ->options(json_decode($configuration->options, true))
                                ->help($helpWithLink, '')
                                ->rules($configuration->rules)
                                ->value($configuration->value);
                            break;
                        case 'checkbox':
                            $form->checkbox($configuration->slug, $configuration->name)
                                ->options(json_decode($configuration->options, true))
                                ->value($configuration->value ? json_decode($configuration->value, true) : [])
                                ->help($helpWithLink, '')
                                ->rules($configuration->rules);
                            break;
                        case 'switch':
                            $form->switch($configuration->slug, $configuration->name)
                                ->states()
                                ->value((bool)$configuration->value)
                                ->help($helpWithLink, '');
                            break;
                        case 'select':
                            $form->select($configuration->slug, $configuration->name)
                                ->options(json_decode($configuration->options, true))
                                ->rules($configuration->rules)
                                ->help($helpWithLink, '')
                                ->value($configuration->value);
                            break;
                        case 'multipleSelect':
                            $form->multipleSelect($configuration->slug, $configuration->name)
                                ->options(json_decode($configuration->options, true))
                                ->value($configuration->value ? json_decode($configuration->value, true) : [])
                                ->help($helpWithLink, '')
                                ->rules($configuration->rules);
                            break;
                        case 'textarea':
                            $form->textarea($configuration->slug, $configuration->name)
                                ->rules('required')
                                ->help($helpWithLink, '')
                                ->value($configuration->value);
                    }

                }
            });
        }

        $form->footer(fn(Form\Footer $footer) => $footer->disableReset());

        $form->tools(function (Form\Tools $tools) {
            $tools->disableList();
            $route = route('admin.auth.configurations.create');
            $tools->append('<a href="' . $route . '" class="btn btn-success btn-sm"><i class="fa fa-plus"></i> 新增</a>');
        });
        return $form;
    }

    public function form(): Form
    {
        $form = new Form($this->model);

        $form->select('type', '配置类型')->options(config('admin.configuration_types'))
            ->help('通过配置文件config/admin.php中的configuration_types配置')
            ->rules('required');
        $form->text('name', '配置名称')->rules('required|max:30')->help('最多30个字符');
        $form->text('slug', '配置标识')
            ->icon('fa-tag')
            ->help('只能包含小写字母和下划线')
            ->rules('required|regex:/^[a-z_]+$/|max:32')
            ->creationRules('required|max:32|unique:' . config('admin.database.configurations_table') . ',slug')
            ->updateRules('required|max:32|unique:' . config('admin.database.configurations_table') . ',slug,{{id}}');
        $form->select('form_type', '表单类型')->options($this->model::FORM_TYPES)->rules('required');
        $form->text('help', '帮助信息')->rules('max:64')->icon('fa-question-circle')
            ->help('显示在表单下方，最多64个字符');
        $form->textarea('options', '选项')
            ->help('表单类型为单选框、多选框、下拉框时必填')
            ->rules('required_if:form_type,select,multipleSelect,radio,checkbox|nullable|json');
        $form->text('rules', '验证规则')
            ->help('表单验证规则，多个规则用|分隔')
            ->rules('nullable');
        $form->number('order', '排序')->default(100)->rules('integer');

        $form->tools(function (Form\Tools $tools) {
            $tools->disableView();
            $tools->disableDelete(false);
        });
        return $form;
    }
}